#coding: utf8
#公历转农历
import datetime
import unittest
import pprint
def Gregorian2Lunar((wCurYear,wCurMonth,wCurDay)):
    #公历每月前面的天数
    wMonthAdd=(0,31,59,90,120,151,181,212,243,273,304,334)
    #农历数据
    wNongliData=(1198,2647,330317,3366,3477,265557,1386,2477,18781,1198\
		,398491,2637,3365,334501,2900,3434,133485,2395,461111,1175\
		,2635,333387,1701,1748,267701,694,2391,133423,1175,396438\
		,3402,3749,331177,1453,694,201326,2350,465197,3221,3402\
		,400202,2901,1386,267611,605,2349,137515,2709,464533,1738\
		,2901,330421,1242,2651,199255,1323,529706,3733,1706,398762\
		,2741,1206,267438,2647,1318,204070,3477,461653,1386,2413\
		,330077,1197,2637,268877,3365,531109,2900,2922,398042,2395\
		,1179,267415,2635,661067,1701,1748,398772,2742,2391,330031\
		,1175,1611,200010,3749,527717,1452,2742,332397,2350,3222\
		,268949,3402,3493,133973,1386,464219,605,2349,334123,2709\
		,2890,267946,2773,592565,1210,2651,395863,1323,2707,265877\
		,1706,2773,18869,1206,51799,2638,3366,44691,3411,1450\
		,26293,2413,92509,1197,2637,55883,3365,3410,44458,2906\
		,1389,18779,1179,62615,2635,2725,46757,1746,2778,27319)
    #取当前公历年、月、日
    #year,month,day = GregorianDate.split('-')
    #wCurYear,wCurMonth,wCurDay=int(year),int(month),int(day)
    wLunarYear,wLunarMonth,wLunarDay=None,None,None
    #计算到初始时间1901年2月19日的天数：1921-2-19(正月初一) 
    nTheDate = (wCurYear - 1901) * 365 + (wCurYear - 1901) / 4 + wCurDay + wMonthAdd[wCurMonth - 1] - 38-11
    if nTheDate<=0:
        return None,None,None
    #闰年
    if (not wCurYear%4) and (wCurMonth>2):
        nTheDate=nTheDate+1
    # 计算农历天干、地支、月、日  
    nIsEnd=False
    m=0
    while not nIsEnd:
        if wNongliData[m]<4095:
            k=11
        else:
            k=12
        n=k
        while n>=0:
            nBit=wNongliData[m]
            for i in range(1,n+1,1):
                nBit=nBit/2
            nBit=nBit%2
            
            if nTheDate<=(29+nBit) :
                nIsEnd=True
                break
            
            nTheDate=nTheDate-29-nBit
            n=n-1
        if nIsEnd:
            break
        m=m+1
        
    
    wCurYear=1901+m
    wCurMonth=k-n+1
    wCurDay=nTheDate
    if wCurDay<0:
        return None,None,None
    
    if k==12:
        if wCurMonth==wNongliData[m]/65536+1:
            wCurMonth=1-wCurMonth
        elif wCurMonth>wNongliData[m]/65536+1:
            wCurMonth=wCurMonth-1
    
    wLunarYear=wCurYear
    Embolism=False#闰月
    if wCurMonth<1:
        wLunarMonth=-wCurMonth
        Embolism=True
    else:
        wLunarMonth=wCurMonth
        Embolism=False
    wLunarDay=wCurDay
    return (wLunarYear,wLunarMonth,wLunarDay,Embolism)
    
#农历转公历
def Lunar2Gregorian((nLunYear,nLunMonth,nLunDay,bEmbolism)):
    #取当前公历年、月、日
    #year,month,day = LunarDate.split('-')
    #wCurYear,wCurMonth,wCurDay=int(year),int(month),int(day)    
    tStart=datetime.date(nLunYear,nLunMonth,nLunDay)
    tSpan=datetime.timedelta(days=1)
    for i in range(0,101):
        wLunYear,wLunMonth,wLunDay,wEmbolism=Gregorian2Lunar((tStart.year,tStart.month,tStart.day))
        if wLunYear==nLunYear and wLunMonth==nLunMonth and wLunDay==nLunDay and bEmbolism==wEmbolism:
            return tStart.year,tStart.month,tStart.day
        tStart+=tSpan
    return (None,None,None)


def GetLunarString((nLunYear,nLunMonth,nLunDay,bEmbolism)):
    # 天干名称
    cTianGan=(u"甲",u"乙",u"丙",u"丁",u"戊",u"己",u"庚",u"辛",u"壬",u"癸")
    #地支名称
    cDizhi=(u"子",u"丑",u"寅",u"卯",u"辰",u"巳",u"午",u"未",u"申",u"酉",u"戌",u"亥")
    #属相名称
    cShuxiang=(u"鼠",u"牛",u"虎",u"兔",u"龙",u"蛇",u"马",u"羊",u"猴",u"鸡",u"狗",u"猪")
    #农历日期名
    cDayName=(u"*",u"初一",u"初二",u"初三",u"初四",u"初五",
		"初六",u"初七",u"初八",u"初九",u"初十",
		"十一",u"十二",u"十三",u"十四",u"十五",
		"十六",u"十七",u"十八",u"十九",u"二十",
		"廿一",u"廿二",u"廿三",u"廿四",u"廿五",       
		"廿六",u"廿七",u"廿八",u"廿九",u"三十")
    #农历月份名
    cMonName=(u"*",u"正",u"二",u"三",u"四",u"五",u"六", "七",u"八",u"九",u"十",u"十一",u"腊")
    #生成属相
    nShuXiang=((nLunYear-4)%60)%12
    if nShuXiang<0 or nShuXiang>=len(cShuxiang):
        raise ValueError,'Error Year for Shuxiang'
    sShuxiang=cShuxiang[nShuXiang]
    #生成农历天干
    nTianGan=((nLunYear-4)%60)%10
    if nTianGan<0 or nTianGan>=len(cTianGan):
        raise ValueError,'Error Year for TianGan'
    sTianGan=cTianGan[nTianGan]
    #生成地支
    nDiZhi=((nLunYear-4)%60)%12
    if nDiZhi<0 or nDiZhi>=len(cDizhi):
        raise ValueError,'Error Year for Dizhi'
    sDiZhi=cDizhi[nDiZhi]
    #生成农历月
    if nLunMonth<0 or nLunMonth>=len(cMonName):
        raise ValueError,'Error Month for LunMonth'      
    sNongliMonth=cMonName[nLunMonth]+u'月'
    if bEmbolism:
        sNongliMonth=u'闰'+sNongliMonth
    #生成农历日
    if nLunDay<0 or nLunDay>=len(cDayName):
        raise ValueError,'Error Month for LunDay'      
    sNongliDay=cDayName[nLunDay]
    return (sShuxiang,sTianGan,sDiZhi,sNongliMonth,sNongliDay)
  
def GetLunarFeastIndex(nGreYear,nGreMonth,nGreDay):
    #数组gLanarHoliDay存放每年的二十四节气对应的阳历日期 
    #每年的二十四节气对应的阳历日期几乎固定，平均分布于十二个月中 
    # 1月 2月 3月 4月 5月 6月 
    #小寒 大寒 立春 雨水 惊蛰 春分 清明 谷雨 立夏 小满 芒种 夏至 
    # 7月 8月 9月 10月 11月 12月 
    #小暑 大暑 立秋 处暑 白露 秋分 寒露 霜降 立冬 小雪 大雪 冬至 
    #********************************** 
    # 节气无任何确定规律,所以只好存表,要节省空间,所以.... 
    #**********************************} 
    #数据格式说明: 
    #如1901年的节气为 
    # 1月 2月 3月 4月 5月 6月 7月 8月 9月 10月 11月 12月 
    # 6, 21, 4, 19, 6, 21, 5, 21, 6,22, 6,22, 8, 23, 8, 24, 8, 24, 8, 24, 8, 23, 8, 22 
    # 9, 6, 11,4, 9, 6, 10,6, 9,7, 9,7, 7, 8, 7, 9, 7, 9, 7, 9, 7, 8, 7, 15 
    #上面第一行数据为每月节气对应日期,15减去每月第一个节气,每月第二个节气减去15得第二行 
    # 这样每月两个节气对应数据都小于16,每月用一个字节存放,高位存放第一个节气数据,低位存放 
    #第二个节气的数据,可得下表 
    gLunarHolDay=(
    0x96, 0xB4, 0x96, 0xA6, 0x97, 0x97, 0x78, 0x79, 0x79, 0x69, 0x78, 0x77, #1901 
    0x96, 0xA4, 0x96, 0x96, 0x97, 0x87, 0x79, 0x79, 0x79, 0x69, 0x78, 0x78, #1902 
    0x96, 0xA5, 0x87, 0x96, 0x87, 0x87, 0x79, 0x69, 0x69, 0x69, 0x78, 0x78, #1903 
    0x86, 0xA5, 0x96, 0xA5, 0x96, 0x97, 0x88, 0x78, 0x78, 0x79, 0x78, 0x87, #1904 
    0x96, 0xB4, 0x96, 0xA6, 0x97, 0x97, 0x78, 0x79, 0x79, 0x69, 0x78, 0x77, #1905 
    0x96, 0xA4, 0x96, 0x96, 0x97, 0x97, 0x79, 0x79, 0x79, 0x69, 0x78, 0x78, #1906 
    0x96, 0xA5, 0x87, 0x96, 0x87, 0x87, 0x79, 0x69, 0x69, 0x69, 0x78, 0x78, #1907 
    0x86, 0xA5, 0x96, 0xA5, 0x96, 0x97, 0x88, 0x78, 0x78, 0x69, 0x78, 0x87, #1908 
    0x96, 0xB4, 0x96, 0xA6, 0x97, 0x97, 0x78, 0x79, 0x79, 0x69, 0x78, 0x77, #1909 
    0x96, 0xA4, 0x96, 0x96, 0x97, 0x97, 0x79, 0x79, 0x79, 0x69, 0x78, 0x78, #1910 
    0x96, 0xA5, 0x87, 0x96, 0x87, 0x87, 0x79, 0x69, 0x69, 0x69, 0x78, 0x78, #1911 
    0x86, 0xA5, 0x96, 0xA5, 0x96, 0x97, 0x88, 0x78, 0x78, 0x69, 0x78, 0x87, #1912 
    0x95, 0xB4, 0x96, 0xA6, 0x97, 0x97, 0x78, 0x79, 0x79, 0x69, 0x78, 0x77, #1913 
    0x96, 0xB4, 0x96, 0xA6, 0x97, 0x97, 0x79, 0x79, 0x79, 0x69, 0x78, 0x78, #1914 
    0x96, 0xA5, 0x97, 0x96, 0x97, 0x87, 0x79, 0x79, 0x69, 0x69, 0x78, 0x78, #1915 
    0x96, 0xA5, 0x96, 0xA5, 0x96, 0x97, 0x88, 0x78, 0x78, 0x79, 0x77, 0x87, #1916 
    0x95, 0xB4, 0x96, 0xA6, 0x96, 0x97, 0x78, 0x79, 0x78, 0x69, 0x78, 0x87, #1917 
    0x96, 0xB4, 0x96, 0xA6, 0x97, 0x97, 0x79, 0x79, 0x79, 0x69, 0x78, 0x77, #1918 
    0x96, 0xA5, 0x97, 0x96, 0x97, 0x87, 0x79, 0x79, 0x69, 0x69, 0x78, 0x78, #1919 
    0x96, 0xA5, 0x96, 0xA5, 0x96, 0x97, 0x88, 0x78, 0x78, 0x79, 0x77, 0x87, #1920 
    0x95, 0xB4, 0x96, 0xA5, 0x96, 0x97, 0x78, 0x79, 0x78, 0x69, 0x78, 0x87, #1921 
    0x96, 0xB4, 0x96, 0xA6, 0x97, 0x97, 0x79, 0x79, 0x79, 0x69, 0x78, 0x77, #1922 
    0x96, 0xA4, 0x96, 0x96, 0x97, 0x87, 0x79, 0x79, 0x69, 0x69, 0x78, 0x78, #1923 
    0x96, 0xA5, 0x96, 0xA5, 0x96, 0x97, 0x88, 0x78, 0x78, 0x79, 0x77, 0x87, #1924 
    0x95, 0xB4, 0x96, 0xA5, 0x96, 0x97, 0x78, 0x79, 0x78, 0x69, 0x78, 0x87, #1925 
    0x96, 0xB4, 0x96, 0xA6, 0x97, 0x97, 0x78, 0x79, 0x79, 0x69, 0x78, 0x77, #1926 
    0x96, 0xA4, 0x96, 0x96, 0x97, 0x87, 0x79, 0x79, 0x79, 0x69, 0x78, 0x78, #1927 
    0x96, 0xA5, 0x96, 0xA5, 0x96, 0x96, 0x88, 0x78, 0x78, 0x78, 0x87, 0x87, #1928 
    0x95, 0xB4, 0x96, 0xA5, 0x96, 0x97, 0x88, 0x78, 0x78, 0x79, 0x77, 0x87, #1929 
    0x96, 0xB4, 0x96, 0xA6, 0x97, 0x97, 0x78, 0x79, 0x79, 0x69, 0x78, 0x77, #1930 
    0x96, 0xA4, 0x96, 0x96, 0x97, 0x87, 0x79, 0x79, 0x79, 0x69, 0x78, 0x78, #1931 
    0x96, 0xA5, 0x96, 0xA5, 0x96, 0x96, 0x88, 0x78, 0x78, 0x78, 0x87, 0x87, #1932 
    0x95, 0xB4, 0x96, 0xA5, 0x96, 0x97, 0x88, 0x78, 0x78, 0x69, 0x78, 0x87, #1933 
    0x96, 0xB4, 0x96, 0xA6, 0x97, 0x97, 0x78, 0x79, 0x79, 0x69, 0x78, 0x77, #1934 
    0x96, 0xA4, 0x96, 0x96, 0x97, 0x97, 0x79, 0x79, 0x79, 0x69, 0x78, 0x78, #1935 
    0x96, 0xA5, 0x96, 0xA5, 0x96, 0x96, 0x88, 0x78, 0x78, 0x78, 0x87, 0x87, #1936 
    0x95, 0xB4, 0x96, 0xA5, 0x96, 0x97, 0x88, 0x78, 0x78, 0x69, 0x78, 0x87, #1937 
    0x96, 0xB4, 0x96, 0xA6, 0x97, 0x97, 0x78, 0x79, 0x79, 0x69, 0x78, 0x77, #1938 
    0x96, 0xA4, 0x96, 0x96, 0x97, 0x97, 0x79, 0x79, 0x79, 0x69, 0x78, 0x78, #1939 
    0x96, 0xA5, 0x96, 0xA5, 0x96, 0x96, 0x88, 0x78, 0x78, 0x78, 0x87, 0x87, #1940 
    0x95, 0xB4, 0x96, 0xA5, 0x96, 0x97, 0x88, 0x78, 0x78, 0x69, 0x78, 0x87, #1941 
    0x96, 0xB4, 0x96, 0xA6, 0x97, 0x97, 0x78, 0x79, 0x79, 0x69, 0x78, 0x77, #1942 
    0x96, 0xA4, 0x96, 0x96, 0x97, 0x97, 0x79, 0x79, 0x79, 0x69, 0x78, 0x78, #1943 
    0x96, 0xA5, 0x96, 0xA5, 0xA6, 0x96, 0x88, 0x78, 0x78, 0x78, 0x87, 0x87, #1944 
    0x95, 0xB4, 0x96, 0xA5, 0x96, 0x97, 0x88, 0x78, 0x78, 0x79, 0x77, 0x87, #1945 
    0x95, 0xB4, 0x96, 0xA6, 0x97, 0x97, 0x78, 0x79, 0x78, 0x69, 0x78, 0x77, #1946 
    0x96, 0xB4, 0x96, 0xA6, 0x97, 0x97, 0x79, 0x79, 0x79, 0x69, 0x78, 0x78, #1947 
    0x96, 0xA5, 0xA6, 0xA5, 0xA6, 0x96, 0x88, 0x88, 0x78, 0x78, 0x87, 0x87, #1948 
    0xA5, 0xB4, 0x96, 0xA5, 0x96, 0x97, 0x88, 0x79, 0x78, 0x79, 0x77, 0x87, #1949 
    0x95, 0xB4, 0x96, 0xA5, 0x96, 0x97, 0x78, 0x79, 0x78, 0x69, 0x78, 0x77, #1950 
    0x96, 0xB4, 0x96, 0xA6, 0x97, 0x97, 0x79, 0x79, 0x79, 0x69, 0x78, 0x78, #1951 
    0x96, 0xA5, 0xA6, 0xA5, 0xA6, 0x96, 0x88, 0x88, 0x78, 0x78, 0x87, 0x87, #1952 
    0xA5, 0xB4, 0x96, 0xA5, 0x96, 0x97, 0x88, 0x78, 0x78, 0x79, 0x77, 0x87, #1953 
    0x95, 0xB4, 0x96, 0xA5, 0x96, 0x97, 0x78, 0x79, 0x78, 0x68, 0x78, 0x87, #1954 
    0x96, 0xB4, 0x96, 0xA6, 0x97, 0x97, 0x78, 0x79, 0x79, 0x69, 0x78, 0x77, #1955 
    0x96, 0xA5, 0xA5, 0xA5, 0xA6, 0x96, 0x88, 0x88, 0x78, 0x78, 0x87, 0x87, #1956 
    0xA5, 0xB4, 0x96, 0xA5, 0x96, 0x97, 0x88, 0x78, 0x78, 0x79, 0x77, 0x87, #1957 
    0x95, 0xB4, 0x96, 0xA5, 0x96, 0x97, 0x88, 0x78, 0x78, 0x69, 0x78, 0x87, #1958 
    0x96, 0xB4, 0x96, 0xA6, 0x97, 0x97, 0x78, 0x79, 0x79, 0x69, 0x78, 0x77, #1959 
    0x96, 0xA4, 0xA5, 0xA5, 0xA6, 0x96, 0x88, 0x88, 0x88, 0x78, 0x87, 0x87, #1960 
    0xA5, 0xB4, 0x96, 0xA5, 0x96, 0x96, 0x88, 0x78, 0x78, 0x78, 0x87, 0x87, #1961 
    0x96, 0xB4, 0x96, 0xA5, 0x96, 0x97, 0x88, 0x78, 0x78, 0x69, 0x78, 0x87, #1962 
    0x96, 0xB4, 0x96, 0xA6, 0x97, 0x97, 0x78, 0x79, 0x79, 0x69, 0x78, 0x77, #1963 
    0x96, 0xA4, 0xA5, 0xA5, 0xA6, 0x96, 0x88, 0x88, 0x88, 0x78, 0x87, 0x87, #1964 
    0xA5, 0xB4, 0x96, 0xA5, 0x96, 0x96, 0x88, 0x78, 0x78, 0x78, 0x87, 0x87, #1965 
    0x95, 0xB4, 0x96, 0xA5, 0x96, 0x97, 0x88, 0x78, 0x78, 0x69, 0x78, 0x87, #1966 
    0x96, 0xB4, 0x96, 0xA6, 0x97, 0x97, 0x78, 0x79, 0x79, 0x69, 0x78, 0x77, #1967 
    0x96, 0xA4, 0xA5, 0xA5, 0xA6, 0xA6, 0x88, 0x88, 0x88, 0x78, 0x87, 0x87, #1968 
    0xA5, 0xB4, 0x96, 0xA5, 0x96, 0x96, 0x88, 0x78, 0x78, 0x78, 0x87, 0x87, #1969 
    0x95, 0xB4, 0x96, 0xA5, 0x96, 0x97, 0x88, 0x78, 0x78, 0x69, 0x78, 0x87, #1970 
    0x96, 0xB4, 0x96, 0xA6, 0x97, 0x97, 0x78, 0x79, 0x79, 0x69, 0x78, 0x77, #1971 
    0x96, 0xA4, 0xA5, 0xA5, 0xA6, 0xA6, 0x88, 0x88, 0x88, 0x78, 0x87, 0x87, #1972 
    0xA5, 0xB5, 0x96, 0xA5, 0xA6, 0x96, 0x88, 0x78, 0x78, 0x78, 0x87, 0x87, #1973 
    0x95, 0xB4, 0x96, 0xA5, 0x96, 0x97, 0x88, 0x78, 0x78, 0x69, 0x78, 0x87, #1974 
    0x96, 0xB4, 0x96, 0xA6, 0x97, 0x97, 0x78, 0x79, 0x78, 0x69, 0x78, 0x77, #1975 
    0x96, 0xA4, 0xA5, 0xB5, 0xA6, 0xA6, 0x88, 0x89, 0x88, 0x78, 0x87, 0x87, #1976 
    0xA5, 0xB4, 0x96, 0xA5, 0x96, 0x96, 0x88, 0x88, 0x78, 0x78, 0x87, 0x87, #1977 
    0x95, 0xB4, 0x96, 0xA5, 0x96, 0x97, 0x88, 0x78, 0x78, 0x79, 0x78, 0x87, #1978 
    0x96, 0xB4, 0x96, 0xA6, 0x96, 0x97, 0x78, 0x79, 0x78, 0x69, 0x78, 0x77, #1979 
    0x96, 0xA4, 0xA5, 0xB5, 0xA6, 0xA6, 0x88, 0x88, 0x88, 0x78, 0x87, 0x87, #1980 
    0xA5, 0xB4, 0x96, 0xA5, 0xA6, 0x96, 0x88, 0x88, 0x78, 0x78, 0x77, 0x87, #1981 
    0x95, 0xB4, 0x96, 0xA5, 0x96, 0x97, 0x88, 0x78, 0x78, 0x79, 0x77, 0x87, #1982 
    0x95, 0xB4, 0x96, 0xA5, 0x96, 0x97, 0x78, 0x79, 0x78, 0x69, 0x78, 0x77, #1983 
    0x96, 0xB4, 0xA5, 0xB5, 0xA6, 0xA6, 0x87, 0x88, 0x88, 0x78, 0x87, 0x87, #1984 
    0xA5, 0xB4, 0xA6, 0xA5, 0xA6, 0x96, 0x88, 0x88, 0x78, 0x78, 0x87, 0x87, #1985 
    0xA5, 0xB4, 0x96, 0xA5, 0x96, 0x97, 0x88, 0x78, 0x78, 0x79, 0x77, 0x87, #1986 
    0x95, 0xB4, 0x96, 0xA5, 0x96, 0x97, 0x88, 0x79, 0x78, 0x69, 0x78, 0x87, #1987 
    0x96, 0xB4, 0xA5, 0xB5, 0xA6, 0xA6, 0x87, 0x88, 0x88, 0x78, 0x87, 0x86, #1988 
    0xA5, 0xB4, 0xA5, 0xA5, 0xA6, 0x96, 0x88, 0x88, 0x88, 0x78, 0x87, 0x87, #1989 
    0xA5, 0xB4, 0x96, 0xA5, 0x96, 0x96, 0x88, 0x78, 0x78, 0x79, 0x77, 0x87, #1990 
    0x95, 0xB4, 0x96, 0xA5, 0x86, 0x97, 0x88, 0x78, 0x78, 0x69, 0x78, 0x87, #1991 
    0x96, 0xB4, 0xA5, 0xB5, 0xA6, 0xA6, 0x87, 0x88, 0x88, 0x78, 0x87, 0x86, #1992 
    0xA5, 0xB3, 0xA5, 0xA5, 0xA6, 0x96, 0x88, 0x88, 0x88, 0x78, 0x87, 0x87, #1993 
    0xA5, 0xB4, 0x96, 0xA5, 0x96, 0x96, 0x88, 0x78, 0x78, 0x78, 0x87, 0x87, #1994 
    0x95, 0xB4, 0x96, 0xA5, 0x96, 0x97, 0x88, 0x76, 0x78, 0x69, 0x78, 0x87, #1995 
    0x96, 0xB4, 0xA5, 0xB5, 0xA6, 0xA6, 0x87, 0x88, 0x88, 0x78, 0x87, 0x86, #1996 
    0xA5, 0xB3, 0xA5, 0xA5, 0xA6, 0xA6, 0x88, 0x88, 0x88, 0x78, 0x87, 0x87, #1997 
    0xA5, 0xB4, 0x96, 0xA5, 0x96, 0x96, 0x88, 0x78, 0x78, 0x78, 0x87, 0x87, #1998 
    0x95, 0xB4, 0x96, 0xA5, 0x96, 0x97, 0x88, 0x78, 0x78, 0x69, 0x78, 0x87, #1999 
    0x96, 0xB4, 0xA5, 0xB5, 0xA6, 0xA6, 0x87, 0x88, 0x88, 0x78, 0x87, 0x86, #2000 
    0xA5, 0xB3, 0xA5, 0xA5, 0xA6, 0xA6, 0x88, 0x88, 0x88, 0x78, 0x87, 0x87, #2001 
    0xA5, 0xB4, 0x96, 0xA5, 0x96, 0x96, 0x88, 0x78, 0x78, 0x78, 0x87, 0x87, #2002 
    0x95, 0xB4, 0x96, 0xA5, 0x96, 0x97, 0x88, 0x78, 0x78, 0x69, 0x78, 0x87, #2003 
    0x96, 0xB4, 0xA5, 0xB5, 0xA6, 0xA6, 0x87, 0x88, 0x88, 0x78, 0x87, 0x86, #2004 
    0xA5, 0xB3, 0xA5, 0xA5, 0xA6, 0xA6, 0x88, 0x88, 0x88, 0x78, 0x87, 0x87, #2005 
    0xA5, 0xB4, 0x96, 0xA5, 0xA6, 0x96, 0x88, 0x88, 0x78, 0x78, 0x87, 0x87, #2006 
    0x95, 0xB4, 0x96, 0xA5, 0x96, 0x97, 0x88, 0x78, 0x78, 0x69, 0x78, 0x87, #2007 
    0x96, 0xB4, 0xA5, 0xB5, 0xA6, 0xA6, 0x87, 0x88, 0x87, 0x78, 0x87, 0x86, #2008 
    0xA5, 0xB3, 0xA5, 0xB5, 0xA6, 0xA6, 0x88, 0x88, 0x88, 0x78, 0x87, 0x87, #2009 
    0xA5, 0xB4, 0x96, 0xA5, 0xA6, 0x96, 0x88, 0x88, 0x78, 0x78, 0x87, 0x87, #2010 
    0x95, 0xB4, 0x96, 0xA5, 0x96, 0x97, 0x88, 0x78, 0x78, 0x79, 0x78, 0x87, #2011 
    0x96, 0xB4, 0xA5, 0xB5, 0xA5, 0xA6, 0x87, 0x88, 0x87, 0x78, 0x87, 0x86, #2012 
    0xA5, 0xB3, 0xA5, 0xB5, 0xA6, 0xA6, 0x87, 0x88, 0x88, 0x78, 0x87, 0x87, #2013 
    0xA5, 0xB4, 0x96, 0xA5, 0xA6, 0x96, 0x88, 0x88, 0x78, 0x78, 0x87, 0x87, #2014 
    0x95, 0xB4, 0x96, 0xA5, 0x96, 0x97, 0x88, 0x78, 0x78, 0x79, 0x77, 0x87, #2015 
    0x95, 0xB4, 0xA5, 0xB4, 0xA5, 0xA6, 0x87, 0x88, 0x87, 0x78, 0x87, 0x86, #2016 
    0xA5, 0xC3, 0xA5, 0xB5, 0xA6, 0xA6, 0x87, 0x88, 0x88, 0x78, 0x87, 0x87, #2017 
    0xA5, 0xB4, 0xA6, 0xA5, 0xA6, 0x96, 0x88, 0x88, 0x78, 0x78, 0x87, 0x87, #2018 
    0xA5, 0xB4, 0x96, 0xA5, 0x96, 0x96, 0x88, 0x78, 0x78, 0x79, 0x77, 0x87, #2019 
    0x95, 0xB4, 0xA5, 0xB4, 0xA5, 0xA6, 0x97, 0x87, 0x87, 0x78, 0x87, 0x86, #2020 
    0xA5, 0xC3, 0xA5, 0xB5, 0xA6, 0xA6, 0x87, 0x88, 0x88, 0x78, 0x87, 0x86, #2021 
    0xA5, 0xB4, 0xA5, 0xA5, 0xA6, 0x96, 0x88, 0x88, 0x88, 0x78, 0x87, 0x87, #2022 
    0xA5, 0xB4, 0x96, 0xA5, 0x96, 0x96, 0x88, 0x78, 0x78, 0x79, 0x77, 0x87, #2023 
    0x95, 0xB4, 0xA5, 0xB4, 0xA5, 0xA6, 0x97, 0x87, 0x87, 0x78, 0x87, 0x96, #2024 
    0xA5, 0xC3, 0xA5, 0xB5, 0xA6, 0xA6, 0x87, 0x88, 0x88, 0x78, 0x87, 0x86, #2025 
    0xA5, 0xB3, 0xA5, 0xA5, 0xA6, 0xA6, 0x88, 0x88, 0x88, 0x78, 0x87, 0x87, #2026 
    0xA5, 0xB4, 0x96, 0xA5, 0x96, 0x96, 0x88, 0x78, 0x78, 0x78, 0x87, 0x87, #2027 
    0x95, 0xB4, 0xA5, 0xB4, 0xA5, 0xA6, 0x97, 0x87, 0x87, 0x78, 0x87, 0x96, #2028 
    0xA5, 0xC3, 0xA5, 0xB5, 0xA6, 0xA6, 0x87, 0x88, 0x88, 0x78, 0x87, 0x86, #2029 
    0xA5, 0xB3, 0xA5, 0xA5, 0xA6, 0xA6, 0x88, 0x88, 0x88, 0x78, 0x87, 0x87, #2030 
    0xA5, 0xB4, 0x96, 0xA5, 0x96, 0x96, 0x88, 0x78, 0x78, 0x78, 0x87, 0x87, #2031 
    0x95, 0xB4, 0xA5, 0xB4, 0xA5, 0xA6, 0x97, 0x87, 0x87, 0x78, 0x87, 0x96, #2032 
    0xA5, 0xC3, 0xA5, 0xB5, 0xA6, 0xA6, 0x88, 0x88, 0x88, 0x78, 0x87, 0x86, #2033 
    0xA5, 0xB3, 0xA5, 0xA5, 0xA6, 0xA6, 0x88, 0x78, 0x88, 0x78, 0x87, 0x87, #2034 
    0xA5, 0xB4, 0x96, 0xA5, 0xA6, 0x96, 0x88, 0x88, 0x78, 0x78, 0x87, 0x87, #2035 
    0x95, 0xB4, 0xA5, 0xB4, 0xA5, 0xA6, 0x97, 0x87, 0x87, 0x78, 0x87, 0x96, #2036 
    0xA5, 0xC3, 0xA5, 0xB5, 0xA6, 0xA6, 0x87, 0x88, 0x88, 0x78, 0x87, 0x86, #2037 
    0xA5, 0xB3, 0xA5, 0xA5, 0xA6, 0xA6, 0x88, 0x88, 0x88, 0x78, 0x87, 0x87, #2038 
    0xA5, 0xB4, 0x96, 0xA5, 0xA6, 0x96, 0x88, 0x88, 0x78, 0x78, 0x87, 0x87, #2039 
    0x95, 0xB4, 0xA5, 0xB4, 0xA5, 0xA6, 0x97, 0x87, 0x87, 0x78, 0x87, 0x96, #2040 
    0xA5, 0xC3, 0xA5, 0xB5, 0xA5, 0xA6, 0x87, 0x88, 0x87, 0x78, 0x87, 0x86, #2041 
    0xA5, 0xB3, 0xA5, 0xB5, 0xA6, 0xA6, 0x88, 0x88, 0x88, 0x78, 0x87, 0x87, #2042 
    0xA5, 0xB4, 0x96, 0xA5, 0xA6, 0x96, 0x88, 0x88, 0x78, 0x78, 0x87, 0x87, #2043 
    0x95, 0xB4, 0xA5, 0xB4, 0xA5, 0xA6, 0x97, 0x87, 0x87, 0x88, 0x87, 0x96, #2044 
    0xA5, 0xC3, 0xA5, 0xB4, 0xA5, 0xA6, 0x87, 0x88, 0x87, 0x78, 0x87, 0x86, #2045 
    0xA5, 0xB3, 0xA5, 0xB5, 0xA6, 0xA6, 0x87, 0x88, 0x88, 0x78, 0x87, 0x87, #2046 
    0xA5, 0xB4, 0x96, 0xA5, 0xA6, 0x96, 0x88, 0x88, 0x78, 0x78, 0x87, 0x87, #2047 
    0x95, 0xB4, 0xA5, 0xB4, 0xA5, 0xA5, 0x97, 0x87, 0x87, 0x88, 0x86, 0x96, #2048 
    0xA4, 0xC3, 0xA5, 0xA5, 0xA5, 0xA6, 0x97, 0x87, 0x87, 0x78, 0x87, 0x86, #2049 
    0xA5, 0xC3, 0xA5, 0xB5, 0xA6, 0xA6, 0x87, 0x88, 0x78, 0x78, 0x87, 0x87); #2050 
    flag=gLunarHolDay[(nGreYear-1901)*12+nGreMonth-1]
    if nGreDay<15:
        iday=15-((flag>>4)&0x0f)
        n=0
    else:
        iday=((flag)&0x0f)+15
        n=1
        
    if iday==nGreDay:
        return (nGreMonth-1)*2+n+1
    return 25

def Get24LunarFeast((nGreYear,nGreMonth,nGreDay)):
    HolText=(u"小寒",u"大寒",u"立春",u"雨水", 
		u"惊蛰",u"春分",u"清明",u"谷雨", 
		u"立夏",u"小满",u"芒种",u"夏至", 
		u"小暑",u"大暑",u"立秋",u"处暑", 
		u"白露",u"秋分",u"寒露",u"霜降", 
		u"立冬",u"小雪",u"大雪",u"冬至",u"")
    
    holiIndex=GetLunarFeastIndex(nGreYear, nGreMonth, nGreDay)
    if holiIndex:
        sFeast=HolText[holiIndex-1]
    else:
        sFeast=u''
    
    nFeastMonth=0
    for n in range(1,31):
        str_Hol=HolText[GetLunarFeastIndex(nGreYear, nGreMonth, n)-1]
        if not str_Hol=='':
            if str_Hol==u"立春":
                if nGreDay>=n: nFeastMonth=13#当天在立春后
                else:nFeastMonth=14                   #当天在立春前
                break
            if str_Hol==u"惊蛰":
                if nGreDay>=n: nFeastMonth=2#当天在惊蛰后
                else: nFeastMonth=1                  #当天在惊蛰前（下同）
                break                
            if str_Hol==u"清明":
                if nGreDay>=n: nFeastMonth=3
                else: nFeastMonth=2
                break  
            if str_Hol==u"立夏":
                if nGreDay>=n: nFeastMonth=4
                else: nFeastMonth=3
                break  
            if str_Hol==u"芒种":
                if nGreDay>=n: nFeastMonth=5
                else: nFeastMonth=4
                break  
            if str_Hol==u"小暑":
                if nGreDay>=n: nFeastMonth=6
                else: nFeastMonth=5
                break  
            if str_Hol==u"立秋":
                if nGreDay>=n: nFeastMonth=7
                else: nFeastMonth=6
                break  
            if str_Hol==u"白露":
                if nGreDay>=n: nFeastMonth=8
                else: nFeastMonth=7
                break  
            if str_Hol==u"寒露":
                if nGreDay>=n: nFeastMonth=9
                else: nFeastMonth=8
                break  
            if str_Hol==u"立冬":
                if nGreDay>=n: nFeastMonth=10
                else: nFeastMonth=9
                break  
            if str_Hol==u"大雪":
                if nGreDay>=n: nFeastMonth=11
                else: nFeastMonth=10
                break  
            if str_Hol==u"小寒":
                if nGreDay>=n: nFeastMonth=12
                else: nFeastMonth=11
                break  
    return (sFeast,nFeastMonth)
# 
def Get8Zi((nGreYear,nGreMonth,nGreDay,nHour,nMinute)):
    (sShuxiang,sTianGan,sDiZhi,sNongliMonth,sNongliDay)=\
        GetLunarString(Gregorian2Lunar((nGreYear,nGreMonth,nGreDay)))
    nTianGan=((nGreYear-4)%60)%10
    #时辰    
    nShiCheng=nHour/2
    if nHour%2==1:#[a<=x<b)半开半闭 
	nShiCheng+=1
    if nShiCheng==12:
	nShiCheng=0
    #分钟
    nFeng=nMinute/10
    if nHour%2==0:
	nFeng+=6#1'分'含120分钟
    
    #年干支
    str_Year=sTianGan+sDiZhi
    #月干支 
    cListMonth=(
           #甲己	 乙庚	     丙辛     丁壬	     戊癸   
        (u"丙寅",u"戊寅",u"庚寅",u"壬寅",u"甲寅"),
        (u"丁卯",u"己卯",u"辛卯",u"癸卯",u"乙卯"),
        (u"戊辰",u"庚辰",u"壬辰",u"甲辰",u"丙辰"),
        (u"己巳",u"辛巳",u"癸巳",u"乙巳",u"丁巳"),
        (u"庚午",u"壬午",u"甲午",u"丙午",u"戊午"),
        (u"辛未",u"癸未",u"乙未",u"丁未",u"己未"),
        (u"壬申",u"甲申",u"丙申",u"戊申",u"庚申"),
	(u"癸酉",u"乙酉",u"丁酉",u"己酉",u"辛酉"),
	(u"甲戌",u"丙戌",u"戊戌",u"庚戌",u"壬戌"),
	(u"乙亥",u"丁亥",u"己亥",u"辛亥",u"癸亥"),
	(u"丙子",u"戊子",u"庚子",u"壬子",u"甲子"),
	(u"丁丑",u"己丑",u"辛丑",u"癸丑",u"乙丑")    
    )
    # 天干名称
    cTianGan=(u"甲",u"乙",u"丙",u"丁",u"戊",u"己",u"庚",u"辛",u"壬",u"癸")
    #地支名称
    cDizhi=(u"子",u"丑",u"寅",u"卯",u"辰",u"巳",u"午",u"未",u"申",u"酉",u"戌",u"亥")
    
    (sFeast,nFeastMonth)=Get24LunarFeast((nGreYear,nGreMonth,nGreDay))
    nMonth=nFeastMonth #二十四节气定年月支
    if nGreMonth==12:
        if nFeastMonth==13:
            nMonth=1
            for nTG in range(0,10):
                if sTianGan==cTianGan[nTG]:
                    sTianGan=cTianGan[(nTG-1)%10]
                    break
            for nDZ in range(0,12):
                if sDiZhi==cDizhi[nDZ]:
                    sDiZhi=cDizhi[(nDZ-1)%12]
                    break
        if nFeastMonth==13:
            nMonth=1
            
    if nTianGan>=5:
        nTianGan-=5
    str_Month=cListMonth[nMonth-1][nTianGan]
    #日干支  
    #1.求元旦干支 以阳历日期来求  
    nGongYuanYear=nGreYear%100#公元纪年的最后两位 
    if nGongYuanYear==0:
	nGongYuanYear=100#百年逢百
    nA=(nGongYuanYear%12)*5
    nB=int(nGongYuanYear/4)
    if not nGongYuanYear%4==0:
        nB=nB+1
    nYuanDanGanZHi=nA+nB
    #2.查表 以cListMonth排列
    #1901～2000年间以甲戌作1向后推某年C的值，既是该年元旦的干支﹙2001～2100年间以己未作1﹚
    nGongYuan=nGreYear
    nX=int(nYuanDanGanZHi/12)%5
    nY=nYuanDanGanZHi%12
    if nGongYuan>2000:
        nX=(nX+4)%5
        if nY+5>12:nX=(nX+1)%5
        nY=(nY+4)%12
    if nGongYuan<=2000:
        if nY+8>12:nX=(nX+1)%5
        nY=(nY+7)%12
    str_YuanDanDay=cListMonth[nY][nX]
    #3.求当日干支
    nDayGan,nDayZhi=0,0
    for n in range(0,10):
        if str_YuanDanDay[:1]==cTianGan[n]:#C源码中文为两个字节，Python为一个
            nDayGan=n
            break
    for k in range(0,12):
        if str_YuanDanDay[1:]==cDizhi[k]:
            nDayZhi=k
            break
    
	#诗诀 
	# 一月干支均减１    二月干加０支加６   三月干减二支加10 
	# 四月干减１支加５  五月干支均减１     六月干加０支加６ 
	# 七月干支均加０    八月干加１支加７   九月干支均加２ 　
	# 十月干加２支加８  十一月干支均加３ 　十二月干加３支加９
    nGanRun,nZhiRun=0,0
    if nGreMonth==1:
	nGanRun=nGanRun-1;nZhiRun=nZhiRun-1
    elif nGreMonth==2:
	nZhiRun=nZhiRun+6
    elif nGreMonth==3:
	nGanRun=nGanRun-2;nZhiRun=nZhiRun+10
    elif nGreMonth==4:
	nGanRun=nGanRun-1;nZhiRun=nZhiRun+5
    elif nGreMonth==5:
	nGanRun=nGanRun-1;nZhiRun=nZhiRun-1
    elif nGreMonth==6:
	nZhiRun+=6
    elif nGreMonth==8:
	nGanRun+=1;nZhiRun+=7
    elif nGreMonth==9:
	nGanRun+=2;nZhiRun+=2
    elif nGreMonth==10:
	nGanRun+=2;nZhiRun+=8
    elif nGreMonth==11:
	nGanRun+=3;nZhiRun+=3
    elif nGreMonth==12:
	nGanRun+=3;nZhiRun+=9
	
    nRunYear=0
    #四年一闰,百年不闰,四百年再闰
    if (nGreYear%400==0) or (not nGreYear%100==0) and (nGreYear%4==0):
	if nGreMonth>2:
	    nRunYear+=1
    # (nDayGan）+（nDay）+（所求月的天干加减数、闰年三月以后减1）÷10
    nTodayGan=(nDayGan+nGreDay+nGanRun+nRunYear)%10
    #（所求年份的元旦地支）+（所求日期）+（所求月的地支加减数、闰年三月以后减1）÷12
    nTodayZhi=(nDayZhi+nGreDay+nZhiRun+nRunYear)%12
    str_TodayGan=cTianGan[nTodayGan]
    str_TodayZhi=cDizhi[nTodayZhi]
    str_Day=str_TodayGan+str_TodayZhi
    #//时干支
    cListTime=(
              #甲己	     乙庚	 丙辛      丁壬	  戊癸   
            (u"甲子",u"丙子",u"戊子",u"庚子",u"壬子"),
            (u"乙丑",u"丁丑",u"己丑",u"辛丑",u"癸丑"),
            (u"丙寅",u"戊寅",u"庚寅",u"壬寅",u"甲寅"),
            (u"丁卯",u"己卯",u"辛卯",u"癸卯",u"乙卯"),
            (u"戊辰",u"庚辰",u"壬辰",u"甲辰",u"丙辰"),
            (u"己巳",u"辛巳",u"癸巳",u"乙巳",u"丁巳"),
            (u"庚午",u"壬午",u"甲午",u"丙午",u"戊午"),
            (u"辛未",u"癸未",u"乙未",u"丁未",u"己未"),
            (u"壬申",u"甲申",u"丙申",u"戊申",u"庚申"),
            (u"癸酉",u"乙酉",u"丁酉",u"己酉",u"辛酉"),
            (u"甲戌",u"丙戌",u"戊戌",u"庚戌",u"壬戌"),
            (u"乙亥",u"丁亥",u"己亥",u"辛亥",u"癸亥")
	);   
    str_Time=cListTime[nShiCheng][nTodayGan%5]
    #考刻分 时上起刻
    nTimeGan=0
    for j in range(0,10):
	if str_Time[:1]==cTianGan[j]:
	    nTimeGan=j
	    break
    str_Minute=cListTime[nFeng][nTimeGan%5]
    
    #四柱 + 考时   十字
    return str_Year,str_Month,str_Day,str_Time,str_Minute
    
    
    
       
       
class FuncTestCase(unittest.TestCase):
    def setUp(self):
        pass
    
    def tearDown(self):
        pass
    def testGregorian2Lunar(self):
        self.assertEqual(Gregorian2Lunar((2012,1,3)),(2011,12,10,False))
    def testLunar2Gregorian(self):
        self.assertEqual(Lunar2Gregorian((2013,4,10,False)),(2013,5,19))       
    def testGetLunarString(self):
        for a in GetLunarString((2013, 5, 26, False)):
            print a 
        for a in GetLunarString(Gregorian2Lunar((2012,6,15))):
            print a
    def testGetLunarFeast(self):
        self.assertEqual(Get24LunarFeast((2013,5,5)),(u'立夏',4))
        self.assertEqual(Get24LunarFeast((2013,5,4)),(u'',3))
    def testGet8Zi(self):
	self.assertEqual(Get8Zi((2012,5,4,0,0)),(u'壬辰',u'甲辰',u'乙丑',u'丙子',u'甲午'))
	#0时0分应为子时午分

if __name__=='__main__':
    #print Gregorian2Lunar('2012-1-3')
    #print Lunar2Gregorian('2013-4-10')
    #print GetLunarString(2013, 5, 26, False)
   # print  Get24LunarFeast((2013,5,4))
    print Get8Zi((2012,5,4,0,0))